#include "mpHttpClitentTests.h"
#include "mpHttpClient.h"
#include "mpHttpConfig.h"
#include "mpHttpParams.h"
#include "mpFileUtils.h"
#include "mpHashUtils.h"
#include "mpAppUtils.h"

#include "mpSingleton.h"
#include "Mapper/mpTemporary.h"
#include "Mapper/mp_http_send_progress_callback.h"
#include "Mapper/mp_http_send_complete_callback.h"
#include "mpLog.h"

#include "Mapper/mpFishMapper.h"
#include "boost/asio/executor_work_guard.hpp"

using namespace MP::HTTP;

mpHttpClitentTests::mpHttpClitentTests()
{
#if 0
    //HTTPS
    _baseUrl = "http://localhost:5000/";                  // "http://127.0.0.1/";
    //HTTP
    _schema = "https";
    _host="localhost";
    _port=5001;
#else
    _baseUrl = "http://localhost:5000/";                  // "http://127.0.0.1/";
    _schema = "http";
    _host="localhost";
    _port=5000;
#endif

    _relativeUri="/";
}

std::string get_save_path(const std::string& name){
    //拼接文件路径
    std::string filePath = MP::FileUtils::get_desktopdir() + PATH_DELIM + "HttpClitentTest" + PATH_DELIM + name;
    //确保所在文件夹存在
    MP::FileUtils::create_directories_forfile(filePath);
    return filePath;
}

//展示请求进度（step = 1 connect ；step = 2 writeData ；step = 3 readData ；）
void send_progress_callback(std::size_t step,std::size_t current,std::size_t total){

    if(step == 1){
        MPLOG_INFO << "########## http connected";
    }
    else if(step == 2){
        if(total >0){
            long double tmp = (long double)current/(long double) total;
            tmp = roundl(tmp * 10000) / 100;
            MPLOG_INFO << "########## http write data: " << tmp << " %"; // current << "/" << total;
        }
        else{
            MPLOG_INFO << "########## http write data: " << current << " bytes";
        }
    }
    else if(step == 3){
        if(total == MP::HTTP::INVALID_SIZE || total == 0 ){
            MPLOG_INFO << "########## http read chunked data: " << current << " bytes";
        }
        else{
            long double tmp = (long double)current/(long double) total;
            tmp = roundl(tmp * 10000) / 100;
            //auto tmp = roundl(current * 100 / total);
            MPLOG_INFO << "########## http read data: " << tmp << " %";
        }
    }
}

void save_to_file(const std::string& name,
                  const std::string& html){

    std::string filePath = get_save_path(name);
    MP::FileUtils::set_file_content(filePath,html,true);
}

void mpHttpClitentTests::initTestCase(){}
void mpHttpClitentTests::cleanupTestCase(){}

void mpHttpClitentTests::case_createClient(){

#ifdef TEST_STRATEGY_COMPLETED


    //读取缺省的
    HttpClient::ptr_s default_client = createHttpClient();

    QVERIFY2(default_client->getBaseAddress().getScheme() == "http","case_createClient_01");
    QVERIFY2(default_client->getBaseAddress().getHost() == "127.0.0.1","case_createClient_02");
    QVERIFY2(default_client->getBaseAddress().getPort() == 80,"case_createClient_03");

    QVERIFY2(default_client->get_connect_timeout() == HttpConfig::GetInstance().get_http_connect_timeout(),"case_createClient_04");
    QVERIFY2(default_client->get_read_timeout() == HttpConfig::GetInstance().get_http_read_timeout(),"case_createClient_05");
    QVERIFY2(default_client->get_write_timeout() == HttpConfig::GetInstance().get_http_write_timeout(),"case_createClient_06");

    //读取已设置的
    HttpConfig::GetInstance().register_client_default_url("maple","https","www.xyz.com",443);
    HttpConfig::GetInstance().set_http_connect_timeout(10);
    HttpConfig::GetInstance().set_http_read_timeout(11);
    HttpConfig::GetInstance().set_http_write_timeout(12);

    HttpClient::ptr_s maple_client = createHttpClientUseName("maple");
    QVERIFY2(maple_client->getBaseAddress().getScheme() == "https","case_createClient_07");
    QVERIFY2(maple_client->getBaseAddress().getHost() == "www.xyz.com","case_createClient_08");
    QVERIFY2(maple_client->getBaseAddress().getPort() == 443,"case_createClient_09");

    QVERIFY2(maple_client->get_connect_timeout() == HttpConfig::GetInstance().get_http_connect_timeout(),"case_createClient_10");
    QVERIFY2(maple_client->get_read_timeout() == HttpConfig::GetInstance().get_http_read_timeout(),"case_createClient_11");
    QVERIFY2(maple_client->get_write_timeout() == HttpConfig::GetInstance().get_http_write_timeout(),"case_createClient_12");

    //重新设置后再次读取
    HttpConfig::GetInstance().register_client_default_url("maple","https","www.abc.com",443);

    maple_client = createHttpClientUseName("maple");
    QVERIFY2(maple_client->getBaseAddress().getScheme() == "https","case_createClient_13");
    QVERIFY2(maple_client->getBaseAddress().getHost() == "www.abc.com","case_createClient_14");
    QVERIFY2(maple_client->getBaseAddress().getPort() == 443,"case_createClient_15");

    QVERIFY2(maple_client->get_connect_timeout() == HttpConfig::GetInstance().get_http_connect_timeout(),"case_createClient_16");
    QVERIFY2(maple_client->get_read_timeout() == HttpConfig::GetInstance().get_http_read_timeout(),"case_createClient_17");
    QVERIFY2(maple_client->get_write_timeout() == HttpConfig::GetInstance().get_http_write_timeout(),"case_createClient_18");

    //根据url创建
    Url url("https://www.hwakun.com.cn/");
    HttpClient::ptr_s hk_client = createHttpClientUseUrl(url);
    QVERIFY2(hk_client->getBaseAddress().getScheme() == "https","case_createClient_19");
    QVERIFY2(hk_client->getBaseAddress().getHost() == "www.hwakun.com.cn","case_createClient_20");
    QVERIFY2(hk_client->getBaseAddress().getPort() == 443,"case_createClient_21");

    QVERIFY2(hk_client->get_connect_timeout() == HttpConfig::GetInstance().get_http_connect_timeout(),"case_createClient_22");
    QVERIFY2(hk_client->get_read_timeout() == HttpConfig::GetInstance().get_http_read_timeout(),"case_createClient_23");
    QVERIFY2(hk_client->get_write_timeout() == HttpConfig::GetInstance().get_http_write_timeout(),"case_createClient_24");


    //读取未设置的,将有异常
    std::string msg;
    try
    {
        HttpClient::ptr_s baidu_client = createHttpClientUseName("baidu");
    }
    catch(HttpException err)
    {
        msg = err.what();
    }

    QVERIFY2(msg == "named 'baidu' http client unregistered","case_createClient_19");



#endif


}

void mpHttpClitentTests::case_createClientAsync(){

#ifdef TEST_STRATEGY_COMPLETED

    boost::asio::io_context context;
    //读取缺省的
    HttpClientAsync::ptr_s default_client = createHttpClientAsync(context);

    QVERIFY2(default_client->getBaseAddress().getScheme() == "http","case_createClientAsync_01");
    QVERIFY2(default_client->getBaseAddress().getHost() == "127.0.0.1","case_createClientAsync_02");
    QVERIFY2(default_client->getBaseAddress().getPort() == 80,"case_createClientAsync_03");

    QVERIFY2(default_client->get_connect_timeout() == HttpConfig::GetInstance().get_http_connect_timeout(),"case_createClientAsync_04");
    QVERIFY2(default_client->get_read_timeout() == HttpConfig::GetInstance().get_http_read_timeout(),"case_createClientAsync_05");
    QVERIFY2(default_client->get_write_timeout() == HttpConfig::GetInstance().get_http_write_timeout(),"case_createClientAsync_06");

    //读取已设置的
    HttpConfig::GetInstance().register_client_default_url("maple","https","www.xyz.com",443);
    HttpConfig::GetInstance().set_http_connect_timeout(10);
    HttpConfig::GetInstance().set_http_read_timeout(11);
    HttpConfig::GetInstance().set_http_write_timeout(12);

    HttpClientAsync::ptr_s maple_client = createHttpClientAsyncUseName(context,"maple");
    QVERIFY2(maple_client->getBaseAddress().getScheme() == "https","case_createClientAsync_07");
    QVERIFY2(maple_client->getBaseAddress().getHost() == "www.xyz.com","case_createClientAsync_08");
    QVERIFY2(maple_client->getBaseAddress().getPort() == 443,"case_createClientAsync_09");

    QVERIFY2(maple_client->get_connect_timeout() == HttpConfig::GetInstance().get_http_connect_timeout(),"case_createClientAsync_10");
    QVERIFY2(maple_client->get_read_timeout() == HttpConfig::GetInstance().get_http_read_timeout(),"case_createClientAsync_11");
    QVERIFY2(maple_client->get_write_timeout() == HttpConfig::GetInstance().get_http_write_timeout(),"case_createClientAsync_12");

    //重新设置后再次读取
    HttpConfig::GetInstance().register_client_default_url("maple","https","www.abc.com",443);

    maple_client = createHttpClientAsyncUseName(context,"maple");
    QVERIFY2(maple_client->getBaseAddress().getScheme() == "https","case_createClientAsync_13");
    QVERIFY2(maple_client->getBaseAddress().getHost() == "www.abc.com","case_createClientAsync_14");
    QVERIFY2(maple_client->getBaseAddress().getPort() == 443,"case_createClientAsync_15");

    QVERIFY2(maple_client->get_connect_timeout() == HttpConfig::GetInstance().get_http_connect_timeout(),"case_createClientAsync_16");
    QVERIFY2(maple_client->get_read_timeout() == HttpConfig::GetInstance().get_http_read_timeout(),"case_createClientAsync_17");
    QVERIFY2(maple_client->get_write_timeout() == HttpConfig::GetInstance().get_http_write_timeout(),"case_createClientAsync_18");

    //根据url创建
    Url url("https://www.hwakun.com.cn/");
    HttpClientAsync::ptr_s hk_client = createHttpClientAsyncUseUrl(context,url);
    QVERIFY2(hk_client->getBaseAddress().getScheme() == "https","case_createClientAsync_19");
    QVERIFY2(hk_client->getBaseAddress().getHost() == "www.hwakun.com.cn","case_createClientAsync_20");
    QVERIFY2(hk_client->getBaseAddress().getPort() == 443,"case_createClientAsync_21");

    QVERIFY2(hk_client->get_connect_timeout() == HttpConfig::GetInstance().get_http_connect_timeout(),"case_createClientAsync_22");
    QVERIFY2(hk_client->get_read_timeout() == HttpConfig::GetInstance().get_http_read_timeout(),"case_createClientAsync_23");
    QVERIFY2(hk_client->get_write_timeout() == HttpConfig::GetInstance().get_http_write_timeout(),"case_createClientAsync_24");

    //读取未设置的,将有异常
    std::string msg;
    try
    {
        HttpClientAsync::ptr_s baidu_client = createHttpClientAsyncUseName(context,"baidu");
    }
    catch(HttpException err)
    {
        msg = err.what();
    }

    QVERIFY2(msg == "named 'baidu' http client unregistered","case_createClient_19");


#endif


}

void mpHttpClitentTests::case_get(){

#ifdef TEST_STRATEGY_COMPLETED


    HttpClient::ptr_s client = createHttpClient();
    client->getBaseAddress().setBaseUrl(_baseUrl);
    //    auto callback = [](std::size_t step,std::size_t current,std::size_t total) -> void
    //    {
    //        MPLOG_ERROR << step << ":" << current << "-" << total;
    //    };
    //    HttpResponseMessage::ptr_s resp = client->get("/weatherforecast",callback);

    HttpResponseMessage::ptr_s resp = client->get("/weatherforecast",send_progress_callback);
    QVERIFY2(resp->isSuccess(),"case_get");

    save_to_file("get.html",resp->getHttpResponseContent()->getData());

#endif

}

void mpHttpClitentTests::case_get_None(){

#ifdef TEST_STRATEGY_COMPLETED

    HttpClient::ptr_s client = createHttpClient();
    client->getBaseAddress().setData(_schema,_host,_port);

    std::stringstream straeam;
    bool isSuccess = client->getStream("/api/fish/123456",straeam);
    QVERIFY2(isSuccess,"case_get_None_01");
    save_to_file("case_get_None.html",straeam.str());

    FishInfo fish;
    ServerSideErrorInfo err;
    MP::Mapper::jsonStringMapperToObject(straeam,fish,err);

    QVERIFY2(!err.ServerSideHasError(),"case_get_None_02");
    QVERIFY2(fish.Name.empty(),"case_get_None_03");
    QVERIFY2(fish.Pinyin.empty(),"case_get_None_04");
    QVERIFY2(fish.Describe.empty(),"case_get_None_05");

#endif

}

void mpHttpClitentTests::case_getStream(){

#ifdef TEST_STRATEGY_COMPLETED

    HttpClient::ptr_s client = createHttpClient();
    client->getBaseAddress().setData(_schema,_host,_port);

    std::stringstream straeam;
    bool isSuccess = client->getStream("/api/fish/9527",straeam);
    QVERIFY2(isSuccess,"case_getStream_01");
    save_to_file("case_getStream.html",straeam.str());

    FishInfo fish;
    ServerSideErrorInfo err;
    MP::Mapper::jsonStringMapperToObject(straeam,fish,err);

    QVERIFY2(!err.ServerSideHasError(),"case_getStream_02");

    QVERIFY2(fish.Id == 9527,"case_getStream_03");
    QVERIFY2(fish.Name == "青鱼","case_getStream_04");
    QVERIFY2(fish.Pinyin == "qinyu","case_getStream_05");
    QVERIFY2(fish.Describe == "青鱼（Mylopharyngodon piceus）又叫黑鲩，全身有较大的鳞片。外形很像草鱼，但全身的鳞片和鱼鳍都带灰黑色。青鱼的名字也由此而来"
             ,"case_getStream_06");
    QVERIFY2(fish.IsLivingInSea == false,"case_getStream_07");

#endif

}

void mpHttpClitentTests::case_getStreamList(){

#ifdef TEST_STRATEGY_COMPLETED

    HttpClient::ptr_s client = createHttpClient();
    client->getBaseAddress().setData(_schema,_host,_port);
    //获取集合List
    std::stringstream straeam;
    bool isSuccess = client->getStream("/api/fish",straeam);
    QVERIFY2(isSuccess,"case_getStreamList_01");

    std::vector<FishInfo> list;
    ServerSideErrorInfo err;
    MP::Mapper::jsonStringMapperToObjectList(straeam,list,err);

    QVERIFY2(!err.ServerSideHasError(),"case_getStreamList_02");
    QVERIFY2(list.size() > 0,"case_getStreamList_03");

    save_to_file("case_getStreamList.html",straeam.str());

#endif

}

void mpHttpClitentTests::case_post_delete_json(){

#ifdef TEST_STRATEGY_COMPLETED

    HttpClient::ptr_s client = createHttpClient();
    client->getBaseAddress().setBaseUrl(_baseUrl);

    FishInfo fish_post;
    FishInfo fish_get;
    //先POST上去
    {
        fish_post.Id = 3306;
        fish_post.Name = "三文鱼";
        fish_post.Pinyin = "sanwenyu";
        fish_post.Describe = "三文鱼是部分鲑科鱼类的俗称，也叫大马哈鱼。三文鱼是世界名贵鱼类之一。鳞小刺少，肉色橙红，肉质细嫩鲜美，口感爽滑，既可直接生食，又能烹制菜肴，是深受人们喜爱的鱼类";
        fish_post.IsLivingInSea = true;

        std::string json;
        MP::Mapper::objectMapperToJsonString(fish_post,json);

        HttpRequestContent::ptr_s requestContent = createHttpRequestJsonContent(json);
        HttpResponseMessage::ptr_s rep_post = client->post("/api/fish",requestContent,send_progress_callback);

        QVERIFY2(rep_post->isSuccess(),"case_post_delete_json_01");
    }


    //再GET回来
    {
        std::stringstream get_straeam;
        bool isSuccess = client->getStream("/api/fish/3306",get_straeam);
        QVERIFY2(isSuccess,"case_post_delete_json_02");
        save_to_file("case_post_delete_json_1.html",get_straeam.str());

        ServerSideErrorInfo err;
        MP::Mapper::jsonStringMapperToObject(get_straeam,fish_get,err);

        QVERIFY2(!err.ServerSideHasError(),"case_post_delete_json_03");

        QVERIFY2(fish_post.Id == fish_get.Id,"case_post_delete_json_04");
        QVERIFY2(fish_post.Name == fish_get.Name,"case_post_delete_json_05");
        QVERIFY2(fish_post.Pinyin == fish_get.Pinyin,"case_post_delete_json_06");
        QVERIFY2(fish_post.Describe == fish_get.Describe,"case_post_delete_json_07");
        QVERIFY2(fish_post.IsLivingInSea == fish_get.IsLivingInSea,"case_post_delete_json_08");
    }

    //最后DELETE掉
    {
        HttpResponseMessage::ptr_s rep_delete = client->del("/api/fish/3306");

        QVERIFY2(rep_delete->isSuccess(),"case_post_delete_json_09");
    }

    //再GET 一次，将返回空
    {
        std::stringstream get_straeam;
        bool isSuccess = client->getStream("/api/fish/3306",get_straeam);
        QVERIFY2(isSuccess,"case_post_delete_json_10");
        save_to_file("case_post_delete_json_2.html",get_straeam.str());
        //返回空
        QVERIFY2(get_straeam.rdbuf()->in_avail() == 0,"case_post_delete_json_11");
    }

#endif

}

void mpHttpClitentTests::case_post_delete_form(){

#ifdef TEST_STRATEGY_COMPLETED

    HttpClient::ptr_s client = createHttpClient();
    client->getBaseAddress().setBaseUrl(_baseUrl);

    FishInfo fish_post;
    FishInfo fish_get;
    //先POST上去
    {
        fish_post.Id = 3307;
        fish_post.Name = "金枪鱼";
        fish_post.Pinyin = "jinqiangyu";
        fish_post.Describe = "金枪鱼是可将体温维持在比周围水体温度高的物种。它们是一些活跃而敏捷的食肉动物，拥有光滑的流线型身体，也是游动速度最快的远洋鱼类之一。金枪鱼可在温暖海域中发现，成为一种大量商业捕捞的鱼类，也是钓鱼活动当中的一种受欢迎鱼类。由于人类的过度捕捞，蓝鳍金枪鱼等部分金枪鱼物种已接近灭绝。";
        fish_post.IsLivingInSea = true;

        std::string form;
        MP::Mapper::objectMapperToFormString(fish_post,form);
        HttpRequestContent::ptr_s requestContent = createHttpRequestFormContent(form);

        HttpResponseMessage::ptr_s rep_post = client->post("/api/fish/post2",requestContent,send_progress_callback);

        QVERIFY2(rep_post->isSuccess(),"case_post_delete_form_01");
    }


    //再GET回来
    {
        std::stringstream get_straeam;
        bool isSuccess = client->getStream("/api/fish/3307",get_straeam);
        QVERIFY2(isSuccess,"case_post_delete_form_02");
        save_to_file("case_post_delete_form_1.html",get_straeam.str());

        ServerSideErrorInfo err;
        MP::Mapper::jsonStringMapperToObject(get_straeam,fish_get,err);

        QVERIFY2(!err.ServerSideHasError(),"case_post_delete_form_03");

        QVERIFY2(fish_post.Id == fish_get.Id,"case_post_delete_form_04");
        QVERIFY2(fish_post.Name == fish_get.Name,"case_post_delete_form_05");
        QVERIFY2(fish_post.Pinyin == fish_get.Pinyin,"case_post_delete_form_06");
        QVERIFY2(fish_post.Describe == fish_get.Describe,"case_post_delete_form_07");
        QVERIFY2(fish_post.IsLivingInSea == fish_get.IsLivingInSea,"case_post_delete_form_08");
    }

    //最后DELETE掉
    {
        HttpResponseMessage::ptr_s rep_delete = client->del("/api/fish/3307");

        QVERIFY2(rep_delete->isSuccess(),"case_post_delete_form_09");
    }

    //再GET 一次，将返回空
    {
        std::stringstream get_straeam;
        bool isSuccess = client->getStream("/api/fish/3307",get_straeam);
        QVERIFY2(isSuccess,"case_post_delete_form_10");
        save_to_file("case_post_delete_form_2.html",get_straeam.str());
        //返回空
        QVERIFY2(get_straeam.rdbuf()->in_avail() == 0,"case_post_delete_form_11");
    }

#endif

}

void mpHttpClitentTests::case_timeout_success(){

#ifdef TEST_STRATEGY_COMPLETED

    HttpClient::ptr_s client = createHttpClient();
    //client->getBaseAddress().setBaseUrl(_baseUrl);
    client->getBaseAddress().setData(_schema,_host,_port);
    client->set_read_timeout(35);
    HttpResponseMessage::ptr_s resp = client->get("/api/timeout");
    QVERIFY2(resp->isSuccess(),"case_timeout_success_01");

#endif

}

void mpHttpClitentTests::case_timeout_fail(){

#ifdef TEST_STRATEGY_COMPLETED

    HttpClient::ptr_s client = createHttpClient();
    //client->getBaseAddress().setBaseUrl(_baseUrl);
    client->getBaseAddress().setData(_schema,_host,_port);
    client->set_read_timeout(5);
    HttpResponseMessage::ptr_s resp = client->get("/api/timeout");
    QVERIFY2(!resp->isSuccess(),"case_timeout_fail_01");
    QVERIFY2(resp->getSendStatuCode() == HTTP_SEND_STATU_CODE::ErrTimeout,"case_timeout_fail_02");

#endif

}

void mpHttpClitentTests::case_download_none(){

#ifdef TEST_STRATEGY_COMPLETED


    std::string fileName = "case_download_none.jpg";
    std::string filePath = get_save_path(fileName);

    HttpClient::ptr_s client = createHttpClient();
    client->getBaseAddress().setBaseUrl(_baseUrl);
    bool isSuccess = client->download("/api/filesystem/" + fileName,filePath,0, http_send_progress_callback(fileName));

    QVERIFY2(!isSuccess,"case_download_none_01");

#endif

}

void mpHttpClitentTests::case_upload(){

#ifdef TEST_STRATEGY_COMPLETED

    std::string fileName = "test.jpg";
    std::string downloadFileName = "case_upload.jpg";

    std::string path = MP::FileUtils::get_appdir() + PATH_DELIM + fileName;
    std::string downloadFilePath = get_save_path(downloadFileName);

    //确保待上传的文件存在
    QVERIFY2(MP::FileUtils::check_file_isexist(path),"case_upload_01");

    //创建Client
    HttpClient::ptr_s client = createHttpClient();
    client->getBaseAddress().setData(_schema,_host,_port);

    //执行POST
    HttpRequestContent::ptr_s req_file_content = createHttpRequestFileContent(path);
    HttpResponseMessage::ptr_s rep_upload = client->post("/api/filesystem?name=" + fileName,req_file_content,http_send_progress_callback(fileName));
    QVERIFY2(rep_upload->isSuccess(),"case_upload_02");
    QVERIFY2(rep_upload->getHttpResponseContent()->getData() == "true","case_upload_03");

    //执行Download下载刚刚上传的文件(下载前，先查看Head状态)
    HttpResponseMessage::ptr_s rep_head = client->head("/api/filesystem/" + fileName);
    QVERIFY2(rep_head->isSuccess(),"case_upload_04");
    QVERIFY2(rep_head->getHttpResponseHeaders().getHeader("Accept-Ranges") == "bytes","case_upload_05");

    bool isSuccess = client->download("/api/filesystem/" + fileName,downloadFilePath,0,http_send_progress_callback(fileName));
    QVERIFY2(isSuccess,"case_upload_06");

    //最后比较前后两个文件的MD5是否一致
    std::string md5;
    std::string download_md5;
    QVERIFY2(MP::HashUtils::file_md5_hex(path,md5),"case_upload_07");
    QVERIFY2(MP::HashUtils::file_md5_hex(downloadFilePath,download_md5),"case_upload_08");

    QVERIFY2(md5 == download_md5,"case_upload_09");

#endif

}

void mpHttpClitentTests::case_upload_form(){

#ifdef TEST_STRATEGY_COMPLETED

    std::string fileName = "test.jpg";
    std::string fileName2 = "uft8.txt";
    std::string downloadFileName = "case_upload_form.dat";

    std::string path = MP::FileUtils::get_appdir() + PATH_DELIM + fileName;
    std::string path2 = MP::FileUtils::get_appdir() + PATH_DELIM + fileName2;
    std::string downloadFilePath = get_save_path(downloadFileName);

    //确保待上传的文件存在
    QVERIFY2(MP::FileUtils::check_file_isexist(path),"case_upload_form_01");

    //创建Client
    HttpClient::ptr_s client = createHttpClient();
    client->getBaseAddress().setBaseUrl(_baseUrl);

    //执行表单提交
    HttpRequestMultipartContent::ptr_s req_form_content = createHttpRequestMultipartContent();
    req_form_content->addFormData("Message","just for test");
    req_form_content->addFormData("Message2","just for test 2");
    req_form_content->addFormFile("test_form.jpg","test_form.jpg",path);
    req_form_content->addFormFile("uft8_form.txt","uft8_form.txt",path2);

    HttpResponseMessage::ptr_s rep_upload = client->post("/api/filesystem/UploadFormModel",req_form_content,http_send_progress_callback(fileName));
    QVERIFY2(rep_upload->isSuccess(),"case_upload_form_02");
    QVERIFY2(rep_upload->getHttpResponseContent()->getData() == "true","case_upload_form_03");

    //执行Download下载刚刚上传的文件(下载前，先查看Head状态)
    HttpResponseMessage::ptr_s rep_head = client->head("/api/filesystem/uft8_form.txt");
    QVERIFY2(rep_head->isSuccess(),"case_upload_form_04");
    QVERIFY2(rep_head->getHttpResponseHeaders().getHeader("Accept-Ranges") == "bytes","case_upload_form_05");

    bool isSuccess = client->download("/api/filesystem/uft8_form.txt",downloadFilePath,0,http_send_progress_callback("uft8_form.txt"));
    QVERIFY2(isSuccess,"case_upload_form_06");

    //最后比较前后两个文件的MD5是否一致
    std::string md5;
    std::string download_md5;
    QVERIFY2(MP::HashUtils::file_md5_hex(path2,md5),"case_upload_form_07");
    QVERIFY2(MP::HashUtils::file_md5_hex(downloadFilePath,download_md5),"case_upload_form_08");

    QVERIFY2(md5 == download_md5,"case_upload_form_09");

#endif

}

void mpHttpClitentTests::case_run_async_useOwnThread(){

#ifdef TEST_STRATEGY_COMPLETED

    boost::asio::io_context context;
    HttpClientAsync::ptr_s client = createHttpClientAsync(context);
    client->getBaseAddress().setData(_schema,_host,_port);
    //get [one req]
    {
        client->getAsync("/weatherforecast",
                         http_send_complete_callback("weatherforecast"),
                         http_send_progress_callback("weatherforecast"));

        context.run();
    }
    //get [four req]
    {

        context.restart();
        client->getAsync("/api/fish",
                         http_send_complete_callback("fish"),
                         http_send_progress_callback("fish"));

        client->getAsync("/api/fish/9527",
                         http_send_complete_callback("fish_9527"),
                         http_send_progress_callback("fish_9527"));

        client->getAsync("/api/fish/9528",
                         http_send_complete_callback("fish_9528"),
                         http_send_progress_callback("fish_9528"));

        client->getAsync("/api/fish/9529",
                         http_send_complete_callback("fish_9529"),
                         http_send_progress_callback("fish_9529"));

        context.run();
    }

    //upload

    std::string fileName = "test.jpg";
    {
        context.restart();
        std::string path = MP::FileUtils::get_appdir() + PATH_DELIM + fileName;
        QVERIFY2(MP::FileUtils::check_file_isexist(path),"case_run_async_useOwnThread_01");

        HttpRequestContent::ptr_s req_file_content = createHttpRequestFileContent(path);
        client->postAsync("/api/filesystem?name=" + fileName,
                          req_file_content,
                          http_send_complete_callback(fileName),
                          http_send_progress_callback(fileName));

        context.run();
    }
    //download
    {
        context.restart();

        std::string downloadFileName = "case_run_async_download.jpg";
        std::string downloadFilePath = get_save_path(downloadFileName);
        client->downloadAsync("/api/filesystem/" + fileName,downloadFilePath,0,
                              http_send_complete_callback(downloadFileName),
                              http_send_progress_callback(downloadFileName));

        context.run();
    }


#endif

}

void mpHttpClitentTests::case_run_async_useCustomThread(){

#ifdef TEST_STRATEGY_COMPLETED

    boost::asio::io_context context;
    boost::asio::executor_work_guard<boost::asio::io_context::executor_type> work(context.get_executor());
    std::vector<std::thread> threads;

    //    boost::thread_group worker_threads;
    //    for( int x = 0; x < 1; ++x )      //线程个数可调整
    //    {
    //        worker_threads.create_thread( boost::bind( &WorkerThread, io_service ) );    //一个io_service
    //    }
    int threadNum = 4;
    for (int i = 0; i < threadNum; ++i)
    {
        threads.emplace_back([&] (){ context.run(); });
    }

    HttpClientAsync::ptr_s client = createHttpClientAsync(context);
    client->getBaseAddress().setData(_schema,_host,_port);
    //get
    client->getAsync("/weatherforecast",
                     http_send_complete_callback("weatherforecast"),
                     http_send_progress_callback("weatherforecast"));

    client->getAsync("/api/fish",
                     http_send_complete_callback("fish"),
                     http_send_progress_callback("fish"));

    client->getAsync("/api/fish/9527",
                     http_send_complete_callback("fish_9527"),
                     http_send_progress_callback("fish_9527"));

    client->getAsync("/api/fish/9528",
                     http_send_complete_callback("fish_9528"),
                     http_send_progress_callback("fish_9528"));

    client->getAsync("/api/fish/9529",
                     http_send_complete_callback("fish_9529"),
                     http_send_progress_callback("fish_9529"));

    work.reset();
    for (auto &t: threads)
    {
        t.join();
    }

#endif


}
